/**
 * @author kovacs peter
 *
 * This example is based on the following book:
 *
 * Title: Programmming Scala
 * Author: Dean Wampler and Alex Payne
 * Published by: O'Reilly Media, Inc.
 * ISBN: 978-0-596-15595-7
 *
 */
package hu.kovacsp.scala.discovery.traits.ui2{
  import hu.kovacsp.scala.discovery.traits.observer.Subject
  import hu.kovacsp.scala.discovery.traits.ui.Widget
  
  /*
   The Clickable trait looks just like a Java interface; it is completely abstract. It defines
   a single, abstract method, click. The method is abstract because it has no body. If
   Clickable were a class, we would have to add the abstract keyword in front of the
   class keyword. This is not necessary for traits.
   */

  trait Clickable {
    def click()
  }

  class Button(val label: String) extends Widget with Clickable {
    def click() = {
// Logic to give the appearance of clicking a button...
    }
  }

  /*
   The ObservableClicks trait extends Clickable and mixes in Subject. It then overrides
   the click method with an implementation that looks almost the same as the overridden
   method shown in “Traits As Mixins” on page 76. The important difference is the
   abstract keyword.
   Look closely at this method. It calls super.click(), but what is super in this case? At
   this point, it could only appear to be Clickable, which declares but does not define the
   click method, or it could be Subject, which doesn’t have a click method. So, super
   can’t be bound, at least not yet.
   In fact, super will be bound when this trait is mixed into an instance that defines a
   concrete click method, such as Button. Therefore, we need an abstract keyword on
   ObservableClicks.click to tell the compiler (and the reader) that click is not yet fully
   implemented, even though ObservableClicks.click has a body.

   (Except for declaring abstract classes, the abstract keyword is only required
   on a method in a trait when the method has a body, but it calls
   the super method that doesn’t have a concrete implementation in
   parents of the trait.)
   */
   trait ObservableClicks extends Clickable with Subject {
      abstract override def click() = {
        super.click()
        notifyObservers
      }
    }


   trait VetoableClicks extends Clickable with Subject {
      val maxAllowed = 1 // default
      private var count = 0
      abstract override def click() = {
        if (count < maxAllowed) {
          count += 1
          super.click()
        }
      }
   }
  }